<?php

/**
 * 杉德支付 充值
 */
class Api_Sandpay extends PhalApi_Api
{
	
	public function getRules()
	{
		return array(
			'sand'        => array(
				'uid'      => array('name' => 'uid', 'type' => 'int', 'min' => 1, 'require' => true, 'desc' => '用户ID'),
				'token'    => array('name' => 'token', 'type' => 'string', 'require' => true, 'desc' => '用户Token'),
				'changeid' => array('name' => 'changeid', 'type' => 'int', 'require' => true, 'desc' => '充值规则ID'),
				'coin'     => array('name' => 'coin', 'type' => 'string', 'require' => true, 'desc' => '钻石'),
				'money'    => array('name' => 'money', 'type' => 'string', 'require' => true, 'desc' => '充值金额'),
			),
			'query'       => array(
				'uid'     => array('name' => 'uid', 'type' => 'int', 'min' => 1, 'require' => true, 'desc' => '用户ID'),
				'token'   => array('name' => 'token', 'type' => 'string', 'require' => true, 'desc' => '用户Token'),
				'orderNo' => array('name' => 'orderNo', 'type' => 'string', 'require' => true, 'desc' => '订单号'),
			),
			'sandRecord'  => array(
				'uid'   => array('name' => 'uid', 'type' => 'int', 'min' => 1, 'require' => true, 'desc' => '用户ID'),
				'token' => array('name' => 'token', 'type' => 'string', 'require' => true, 'desc' => '用户Token'),
				'p'     => array('name' => 'p', 'type' => 'int', 'default' => '1', 'desc' => '页面'),
				'pnum'  => array('name' => 'pnum', 'type' => 'int', 'default' => '10', 'desc' => '每一页数量'),
			),
			'getAliOrder' => array(
				'uid'      => array('name' => 'uid', 'type' => 'int', 'min' => 1, 'require' => true, 'desc' => '用户ID'),
				'token'    => array('name' => 'token', 'type' => 'string', 'require' => true, 'desc' => '用户Token'),
				'changeid' => array('name' => 'changeid', 'type' => 'int', 'require' => true, 'desc' => '充值规则ID'),
				'coin'     => array('name' => 'coin', 'type' => 'string', 'require' => true, 'desc' => '钻石'),
				'money'    => array('name' => 'money', 'type' => 'string', 'require' => true, 'desc' => '充值金额'),
			),
			'getWxOrder'  => array(
				'uid'      => array('name' => 'uid', 'type' => 'int', 'min' => 1, 'require' => true, 'desc' => '用户ID'),
				'token'    => array('name' => 'token', 'type' => 'string', 'require' => true, 'desc' => '用户Token'),
				'changeid' => array('name' => 'changeid', 'type' => 'string', 'require' => true, 'desc' => '充值规则ID'),
				'coin'     => array('name' => 'coin', 'type' => 'string', 'require' => true, 'desc' => '钻石'),
				'money'    => array('name' => 'money', 'type' => 'string', 'require' => true, 'desc' => '充值金额'),
			),
			
			'getChargeRules' => array(
				'uid'   => array('name' => 'uid', 'type' => 'int', 'min' => 1, 'require' => true, 'desc' => '用户ID'),
				'token' => array('name' => 'token', 'type' => 'string', 'require' => true, 'desc' => '用户Token'),
			),
			
			'getFirstChargeRules' => array(
				'uid'   => array('name' => 'uid', 'type' => 'int', 'min' => 1, 'require' => true, 'desc' => '用户ID'),
				'token' => array('name' => 'token', 'type' => 'string', 'require' => true, 'desc' => '用户Token'),
			),
		);
	}
	
	#####################################################################################################################################
	## 各种支付操作
	
	
	// 杉德 支付
	// s1.scbjxs.com/appapi/?service=Sandpay.sand&uid=1487
	public function sand()
	{
		$changeid = checkNull($this->changeid);
		$uid      = checkNull($this->uid);
		$token    = checkNull($this->token);
		$coin     = checkNull($this->coin);
		$money    = checkNull($this->money);
		
		// 验证登录
		$checkToken = checkToken($uid, $token);
		if($checkToken == 700){
			return $this->fail('您的登陆状态失效，请重新登陆！', $checkToken);
		}
		
		
		$desc = '充值';
		$ds   = DIRECTORY_SEPARATOR;
		if(strpos($_SERVER['SERVER_NAME'], 'zhiboxiu.com.cn') === false){
			//测试环境
			$basePath       = dirname(__DIR__).$ds.'Domain'.$ds.'sand'.$ds;
			$publicKeyPath  = $basePath."sand-test.cer";
			$privateKeyPath = $basePath."sanduatprikey.pfx";
			$privateKeyPwd  = "123456";
			$URL            = "https://scfp-uat.sand.com.cn/gateway/trade";
			$mid            = '68888TS125511';
			$orderNo        = "Sandtest".$this->getOrderid($uid);
			
			// 第二个测试环境
			$publicKeyPath  = $basePath."sand_pro.cer";
			$privateKeyPath = $basePath."smsc20240509.pfx";
			$privateKeyPwd  = "135700";
			$URL            = "https://scfp-uat.sand.com.cn/gateway/trade";
			$URL            = "https://cashapi.sandpay.com.cn/gateway/trade";  // 正式
			$mid            = '6888804125511';
		} else{
			//生产环境
			$basePath       = dirname(__DIR__).$ds.'Domain'.$ds.'sand'.$ds;
			$publicKeyPath  = $basePath."sc20240509zb.cer";
			$publicKeyPath  = $basePath."sand_pro.cer";
			$privateKeyPath = $basePath."smsc20240509.pfx";
			$privateKeyPwd  = "135700";
			$URL            = "https://cashapi.sandpay.com.cn/gateway/trade";
			$mid            = '6888804125511';
			$orderNo        = "Sand".$this->getOrderid($uid);
		}
		
		// 私钥秘钥
		$domain = new Domain_Sandpay();
		$pubKey = $domain->loadX509Cert($publicKeyPath);
		$prikey = $domain->loadPk12Cert($privateKeyPath, $privateKeyPwd);
		//var_dump($pubKey);
		//echo '<br><br><br><br>';
		//var_dump($prikey);
		
		//通用公共报文
		$publicdata = [
			"accessMid"   => $mid,
			"timestamp"   => date('Y-m-d H:i:s'),
			"version"     => "4.0.0",
			"signType"    => "RSA",
			"sign"        => "",
			"encryptType" => "AES",   //AES加密
			"encryptKey"  => "",
			"bizData"     => "",
		];
		
		$time = date("Y-m-d H:i:s");
		$time = str_replace(' ', '', $time);
		$time = str_replace('-', '', $time);
		$time = str_replace(':', '', $time);
		
		// 异步返回
		//$configpub  = getConfigPub();
		//$notify_url = $configpub['site'].'/appapi/pay/notify_sand';
		
		// 获取协议类型
		$protocol   = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http';
		$host       = $_SERVER['HTTP_HOST']; // 获取主机名(包括域名和端口)
		$notify_url = $protocol.'://'.$host.'/appapi/pay/notify_sand';
		
		// 保存位订单
		$orderinfo = array("uid" => $uid, "touid" => $uid, "money" => $money, "coin" => $coin, "orderno" => $orderNo, "type" => 7, "status" => 0, "addtime" => time());
		$info      = (new Domain_Charge())->getOrderId($changeid, $orderinfo);
		if($info == 1003){
			return $this->fail('订单信息有误，请重新提交', 1003);
		} elseif(!$info){
			return $this->fail('订单生成失败', 1001);
		}
		
		
		$params = array(
			"marketProduct" => "CSDB",
			//QZF：标准线上收款
			//CSDB：企业杉德宝
			"outReqTime"    => date('Y-m-d H:i:s'),
			"amount"        => $money,
			//funcCodeList
			//APP包装微信小程序	02010005	SDK
			//APP包装支付宝生活号	02020004	SDK
			//APP包装支付宝码付	02020006	SDK
			//银联线上收银台	02030001	SDK
			//快捷充值（推荐）	06030003	SDK/H5
			//H5快捷（WAP支付）	06030001	SDK/H5
			//一键快捷	05030001	SDK/H5
			//杉德宝SDK/杉德宝扫码	02040001	SDK/H5
			//微信公众号	02010002	H5
			//H5包装云函数	02010006	H5
			//H5包装支付宝生活号	02020002	H5
			//H5包装支付宝码付	02020005	H5
			"sdCashierType" => "H5",
			"funcCodeList"  => array("02020002"),
			"payerInfo"     => array(
				"payExtra" => array(
					//array("funcCode" => "06030001","cardNo"=>"6226090000000048"),
					//array("funcCode" => "06030001","cardNo"=>"6226090000000048"),
					//                    array("funcCode" => "06030003",
					//                        "cardNo"=>"620522001026543019",
					//                        "userId"=>"sand12",
					//                       // "phoneNo"=>"手机号",
					//                        "name"=>"姓名",
					//                        "idcardType"=>"1",
					//                        "idcardNumber"=>"身份证",
					//                        ),
					//array("funcCode" => "05030001", "userId" => "sand1"),
					//array("funcCode" => "02010006","subAppId" => "23123213213", "resourceEnv" => "san123123d1"),
					array("funcCode" => "02010002", "subAppId" => "23123213213", "subUserId" => "san123123d1"),
					//array("funcCode" => "02040001"),
				),
				"frontUrl" => "http://test.wcldesign.com.cn",
			),
			"metaOption"    => '[{"s":"Android","n":"","id":"","sc":""},{"s":"IOS","n":"","id":"","sc":""}]',
			"goodsClass"    => "10",
			"mid"           => $mid,
			"description"   => "测试全支付收银台",
			"accessMid"     => $mid,
			"outOrderNo"    => $orderNo,
			"timeOut"       => date('YmdHis', time() + 300),
			"reqReserved"   => array(
				"reqMemo" => "全支付收银台自用摘要",
			),
			"notifyUrl"     => $notify_url,
			"riskmgtInfo"   => array(
				"sourceIp" => "192.168.0.1",
			),
			"jumpScheme"    => "sandcash://scpay",
		);
		
		// 商户签名流程
		// 1. 生成一个16位的随机字符串aseKey，该字符串仅包含大小写字母及数字。
		// 2. 将随机字符串转为byte数组aesKeyBytes，编码格式为UTF_8。
		// 3. 将请求报文中的bizData域转为byte数组，编码格式为UTF_8，并用aesKeyBytes用AES算法对其加密，并对结果进行base64转码，得到加密报文体encryptValueBytes。
		// 4. 将随机字符串byte数组aesKeyBytes使用杉德公钥进行RSA算法加密，并将结果进行base64转码即得到得到sandEncryptKey。
		// 5. 将加密报文体使用商户私钥进行RSA算法签名，得到sign。
		
		if($publicdata['encryptType'] == 'AES'){
			//step1 生成随机数
			$AESKey = $domain->getRandString(16);
			// step2、3: 使用AESKey加密报文 通过aesKeyBytes对Json进行AES加密生成data
			$publicdata['bizData'] = $domain->AESEncrypt($params, $AESKey);   //  AES 模式
			// step4: 把aesKeyBytes通过杉德公钥加密生成encryptKey，encryptType为"AES"
			$publicdata['encryptKey'] = $domain->RSAEncryptByPub($AESKey, $pubKey); //  AES 模式
		}
		
		// step5: 将加密后的data，通过商户私钥进行签名生成sign，signType为"SHA256WithRSA"
		$publicdata['sign'] = $domain->sign($publicdata['bizData'], $prikey);
		
		// 创建文件夹log
		//$this->saveLog($orderNo, " 请求时间:");
		//$this->saveLog($orderNo, " 商户订单号:");
		//$this->saveLog(json_encode($publicdata, 320), " 请求报文明文:");
		
		// step6: post请求
		$result = $domain->http_post_json($URL, $publicdata);
		$arr    = json_decode($result, true);
		if($publicdata['encryptType'] == 'AES'){
			// step6: 使用公钥验签报文$decryptPlainText
			$verify = $domain->verify($arr['bizData'], $arr['sign'], $pubKey);
			if(!is_numeric($verify)){
				return $verify;
			}
			
			// step7: 使用私钥解密AESKey
			$decryptAESKey = $domain->RSADecryptByPri($arr['encryptKey'], $prikey);
			if(!is_string($decryptAESKey)){
				return $decryptAESKey;
			}
			
			// step8: 使用解密后的AESKey解密报文
			$decryptPlainText = json_decode($domain->AESDecrypt($arr['bizData'], $decryptAESKey));
			// 将返回数据写入日志，生产可以删除
			$jsondata1 = json_encode($decryptPlainText);
			$jsondata2 = json_encode($params);
			$jsondata  = $jsondata1.$jsondata2;
			$this->saveLog($jsondata2, '请求返回结果');
		}
		
		$respon = [
			'verify'     => $verify == 1 ? '验签成功!' : '验签失败!',
			//'params'     => json_encode($params, JSON_UNESCAPED_UNICODE),
			//'publicdata' => json_encode($publicdata),
			'params'     => $params,
			'orderNo'    => $orderNo,
			'publicdata' => $publicdata,
			'response'   => $decryptPlainText,
		];
		
		return $this->success(['0' => $respon]);
	}
	
	// 获取杉德 支付记录
	public function sandRecord()
	{
		$uid   = checkNull($this->uid);
		$token = checkNull($this->token);
		$pnum  = checkNull($this->pnum);
		$p     = checkNull($this->p);
		
		// 验证登录
		$checkToken = checkToken($uid, $token);
		if($checkToken == 700){
			//return $this->fail('您的登陆状态失效，请重新登陆！', $checkToken);
		}
		
		$domain = new Domain_Charge();
		$res    = $domain->getRecord($uid, $p, $pnum);
		if($res == 1001){
			return $this->success([], '暂无列表');
		}
		
		return $this->success($res);
	}
	
	// 充值查询
	public function query()
	{
		$uid   = checkNull($this->uid);
		$token = checkNull($this->token);
		// 验证登录
		$checkToken = checkToken($uid, $token);
		if($checkToken == 700){
			return $this->fail('您的登陆状态失效，请重新登陆！', $checkToken);
		}
		
		$orderno = 'Sandtest1075_20240509104541305';
		$orderno = checkNull($this->orderNo);
		list($uid, $time) = explode('_', $orderno);
		
		$mid  = '68888TS125511';
		$desc = '充值';
		$ds   = DIRECTORY_SEPARATOR;
		if(strpos($_SERVER['SERVER_NAME'], 'zhiboxiu.com.cn') === false){
			//测试环境
			$basePath       = dirname(__DIR__).$ds.'Domain'.$ds.'sand'.$ds;
			$publicKeyPath  = $basePath."sand-test.cer";
			$privateKeyPath = $basePath."sanduatprikey.pfx";
			$privateKeyPwd  = "123456";
			$URL            = "https://openapi-uat01.sand.com.cn/v4/sd-receipts/api/trans/trans.order.query";  // 测试
			$mid            = '68888TS125511';
			
			// 第二个测试环境
			$publicKeyPath  = $basePath."sand_pro.cer";
			$privateKeyPath = $basePath."smsc20240509.pfx";
			$privateKeyPwd  = "135700";
			//$URL            = "https://openapi-uat01.sand.com.cn/v4/sd-receipts/api/trans/trans.order.query"; // 测试
			$URL = "https://openapi.sandpay.com.cn/v4/sd-receipts/api/trans/trans.order.query";  // 正式
			$mid = '6888804125511';
		} else{
			//生产环境
			$basePath       = dirname(__DIR__).$ds.'Domain'.$ds.'sand'.$ds;
			$publicKeyPath  = $basePath."sc20240509zb.cer";
			$publicKeyPath  = $basePath."sand_pro.cer";
			$privateKeyPath = $basePath."smsc20240509.pfx";
			$privateKeyPwd  = "135700";
			$URL            = "https://openapi.sandpay.com.cn/v4/sd-receipts/api/trans/trans.order.query";  // 正式
			$mid            = '6888804125511';
		}
		
		// 私钥秘钥
		$domain = new Domain_Sandpay();
		$pubKey = $domain->loadX509Cert($publicKeyPath);
		$prikey = $domain->loadPk12Cert($privateKeyPath, $privateKeyPwd);
		//var_dump($pubKey);
		//echo '<br><br><br><br>';
		//var_dump($prikey);
		
		//通用公共报文
		$publicdata = [
			"accessMid"   => $mid,
			"timestamp"   => date('Y-m-d H:i:s'),
			"version"     => "4.0.0",
			"signType"    => "RSA",
			"sign"        => "",
			"encryptType" => "AES",   //AES加密
			"encryptKey"  => "",
			"bizData"     => "",
		];
		
		// 请求
		$params = ['outReqTime' => substr($time, 0, -3), 'marketProduct' => 'QZF', 'mid' => $mid, 'outOrderNo' => $orderno,];
		
		// 商户签名流程
		// 1. 生成一个16位的随机字符串aseKey，该字符串仅包含大小写字母及数字。
		// 2. 将随机字符串转为byte数组aesKeyBytes，编码格式为UTF_8。
		// 3. 将请求报文中的bizData域转为byte数组，编码格式为UTF_8，并用aesKeyBytes用AES算法对其加密，并对结果进行base64转码，得到加密报文体encryptValueBytes。
		// 4. 将随机字符串byte数组aesKeyBytes使用杉德公钥进行RSA算法加密，并将结果进行base64转码即得到得到sandEncryptKey。
		// 5. 将加密报文体使用商户私钥进行RSA算法签名，得到sign。
		if($publicdata['encryptType'] == 'AES'){
			//step1 生成随机数
			$AESKey = $domain->getRandString(16);
			// step2、3: 使用AESKey加密报文 通过aesKeyBytes对Json进行AES加密生成data
			$publicdata['bizData'] = $domain->AESEncrypt($params, $AESKey);   //  AES 模式
			// step4: 把aesKeyBytes通过杉德公钥加密生成encryptKey，encryptType为"AES"
			$publicdata['encryptKey'] = $domain->RSAEncryptByPub($AESKey, $pubKey); //  AES 模式
		}
		
		// step5: 将加密后的data，通过商户私钥进行签名生成sign，signType为"SHA256WithRSA"
		$publicdata['sign'] = $domain->sign($publicdata['bizData'], $prikey);
		
		// 创建文件夹log
		//$this->saveLog(date("YmdHis"), " 查询：请求时间:");
		//$this->saveLog($orderno, " 查询：商户订单号:");
		//$this->saveLog(json_encode($publicdata, 320), " 查询：请求报文明文:");
		//$this->saveLog(json_encode($params, JSON_UNESCAPED_UNICODE), " 查询：请求报文明文:");
		
		// step6: post请求
		$result = $domain->http_post_json($URL, $publicdata);
		$arr    = json_decode($result, true);
		$this->saveLog($result, " 查询：返回报文明文:");
		if($publicdata['encryptType'] == 'AES'){
			// step6: 使用公钥验签报文$decryptPlainText
			$verify = $domain->verify($arr['bizData'], $arr['sign'], $pubKey);
			if(!is_numeric($verify)){
				return $verify;
			}
			
			// step7: 使用私钥解密AESKey
			$decryptAESKey = $domain->RSADecryptByPri($arr['encryptKey'], $prikey);
			if(!is_string($decryptAESKey)){
				return $decryptAESKey;
			}
			
			// step8: 使用解密后的AESKey解密报文
			$decryptPlainText = json_decode($domain->AESDecrypt($arr['bizData'], $decryptAESKey), true);
			// 将返回数据写入日志，生产可以删除
			$jsondata1 = json_encode($decryptPlainText, JSON_UNESCAPED_UNICODE);
			$jsondata2 = json_encode($params, JSON_UNESCAPED_UNICODE);
			$this->saveLog($jsondata2, ' 查询：请求结果');
			$this->saveLog($jsondata1, ' 查询：返回结果');
		} else{
			return $this->fail();
		}
		
		
		$info = [
			'verify'       => $verify == 1 ? '验签成功!' : '验签失败!',
			//'params'     => json_encode($params, JSON_UNESCAPED_UNICODE),
			//'publicdata' => json_encode($publicdata),
			//'params'       => $params,
			'orderNo'      => $orderno,
			'resultStatus' => $decryptPlainText['orderStatus'],
			'errorDesc'    => $decryptPlainText['errorDesc'] ?? '',
		];
		
		return $this->success(['0' => $info]);
	}
	
	
	/**
	 * 获取首充充值规则列表
	 * @desc 获取首充充值规则列表
	 * @return int code 状态码,0表示成功
	 * @return string msg 提示信息
	 * @return array info 返回信息
	 * @return int info[0]['has_used'] 首充机会是否已用完 0 否 1 是
	 * @return int info[0]['list'] 返回充值规则
	 * @return int info[0]['list'][]['id'] 返回充值规则ID
	 * @return int info[0]['list'][]['title'] 返回充值规则名称
	 * @return int info[0]['list'][]['money'] 返回充值规则金额
	 * @return int info[0]['list'][]['coin'] 返回充值规则钻石数
	 * @return array info[0]['list'][]['list'] 返回充值规则项目列表
	 * @return string info[0]['list'][]['list'][]['name'] 返回充值规则项目列表项的名称
	 * @return string info[0]['list'][]['list'][]['count'] 返回充值规则项目列表项的数量
	 * @return string info[0]['list'][]['list'][]['thumb'] 返回充值规则项目列表项的数量
	 */
	public function getFirstChargeRules()
	{
		$uid        = checkNull($this->uid);
		$token      = checkNull($this->token);
		$checkToken = checkToken($uid, $token);
		if($checkToken == 700){
			return $this->fail('您的登陆状态失效，请重新登陆！', $checkToken);
		}
		
		$domain    = new Domain_Charge();
		$res       = $domain->getFirstChargeRules();
		$configpri = getConfigPri();
		$switch    = $configpri['firstcharge_repeatedly'];
		$has_used  = '0';
		if(!$switch){
			$firstcharge_used = checkUserFirstCharge($uid);
			if($firstcharge_used){
				$has_used = '1';
			}
		}
		
		$info = ['list' => $res, 'has_used' => $has_used];
		
		return $this->success(['0' => $info]);
	}
	
	
	/**
	 * 获取首充充值规则列表
	 * @desc 获取首充充值规则列表
	 * @return int code 状态码,0表示成功
	 * @return string msg 提示信息
	 * @return array info 返回信息
	 * @return int info[0]['has_used'] 首充机会是否已用完 0 否 1 是
	 * @return int info[0]['list'] 返回充值规则
	 * @return int info[0]['list'][]['id'] 返回充值规则ID
	 * @return int info[0]['list'][]['title'] 返回充值规则名称
	 * @return int info[0]['list'][]['money'] 返回充值规则金额
	 * @return int info[0]['list'][]['coin'] 返回充值规则钻石数
	 * @return array info[0]['list'][]['list'] 返回充值规则项目列表
	 * @return string info[0]['list'][]['list'][]['name'] 返回充值规则项目列表项的名称
	 * @return string info[0]['list'][]['list'][]['count'] 返回充值规则项目列表项的数量
	 * @return string info[0]['list'][]['list'][]['thumb'] 返回充值规则项目列表项的数量
	 */
	public function getChargeRules()
	{
		$uid        = checkNull($this->uid);
		$token      = checkNull($this->token);
		$checkToken = checkToken($uid, $token);
		if($checkToken == 700){
			return $this->fail('您的登陆状态失效，请重新登陆！', $checkToken);
		}
		
		$domain = new Domain_User();
		$key    = 'getChargeRules';
		$rules  = getcaches($key);
		if(!$rules){
			$rules = $domain->getChargeRules();
			setcaches($key, $rules);
		}
		
		return $this->success(['0' => $rules]);
	}
	
	
	public function sand2()
	{
		$uid = checkNull($this->uid);
		
		$pass    = '123456';
		$orderNo = $this->getOrderid($uid);
		$amount  = '0.1';
		
		$mid  = '68888TS125511';
		$desc = '充值';
		$post = array(
			'version'     => '4.0.0',
			'accessMid'   => $mid, // 商户号
			'timestamp'   => date('Y-m-d H:i:s', time()),
			'signType'    => 'RSA',
			'encryptType' => 'AES',
			'bizData'     => [
				"marketProduct" => "QZF",
				"mid"           => $mid,
				"outOrderNo"    => $orderNo,
				"description"   => $desc,
				"goodsClass"    => '10',
				"amount"        => $amount,
				"funcCodeList"  => [
					"06030003",
				],
				"payerInfo"     => [
					"payExtra"          => [
						[
							"funcCode"     => "06030003",
							"userId"       => "su19920808",
							"cardNo"       => "6231580202412516189",
							"phoneNo"      => "18711759842",
							"name"         => "张三",
							"idcardType"   => "1",
							"idcardNumber" => "471412199804189842",
						],
					],
					"frontUrl"          => "https://www.baidu.com",  // 支付结束后跳转的网页地址
					"payerIdentityInfo" => [
						"payerLimitFlag" => "1",
						"name"           => "张三",
						"idcardType"     => "1",
						"idcardNumber"   => "471412199804189842",
					],
					"payAccLimit"       => [
						"debit",
						"bal_alipay",
					],
				],
				"timeOut"       => date('YmdHis', time() + 300),
				"notifyUrl"     => "https =>//www.baidu.com",
				"settleInfo"    => [
					"transFlag"            => "S0",
					"s0Remark"             => "S0划款附言",
					"profitSharingFlag"    => "1",
					"profitSharingTimeout" => "20230915110401",
					"settleCurrency"       => "CNY",
				],
				/*"storeInfo"     => [
					"cashierNo"  => "1001",
					"operatorNo" => "1001",
					"storeNo"    => "1001",
					"storeName"  => "联航路店",
					"storeArea"  => "联航路1588号",
				],*/
				"discountInfo"  => [
					"activityNo"     => "1001",
					"discountAmt"    => 0.01,
					"transBlockFlag" => "block",
				],
				"sdCashierType" => "H5",
				"metaOption"    => "[{\"s\":\"Android\",\"n\":\"\",\"id\":\"\",\"sc\":\"\"},{\"s\":\"IOS\",\"n\":\"\",\"id\":\"\",\"sc\":\"\"}]",
				"jumpScheme"    => "sandcash://scpay",
			],
		);
		
		
		$domain     = new Domain_Sandpay();
		$pubKey     = $domain->getSandPublicKey();
		$merchPri   = $domain->getMerchPrivateKey();
		$encryptKey = $domain->getRandString(16);   // 1.生成一个16位的随机字符串aesKey，该字符串仅包含大小写字母及数字。
		
		// 加密报文体
		// 3.将请求报文中明文bizData域转为byte数组，编码格式为UTF_8，并用aesKeyBytes用AES算法（AES/ECB/PKCS5Padding）对其加密，并对结果进行base64转码，得到加密报文体bizData。
		$json_data   = json_encode($post['bizData']);
		$encryptdata = $domain->AESEncrypt($json_data, $encryptKey);
		
		// 4.将随机字符串byte数组aesKeyBytes使用杉德公钥进行RSA算法（RSA/ECB/PKCS1Padding）加密，并将结果进行base64转码即得到encryptKey。
		$resource   = openssl_pkey_get_public($pubKey);
		$encryptKey = $domain->RSAEncryptByPub($encryptKey, $resource);
		// 整理
		$post['encryptKey'] = $encryptKey;
		$post['bizData']    = $encryptdata;
		// 5.将加密报文体使用商户私钥进行RSA算法（SHA256WithRSA）签名，得到sign。
		$post['sign'] = $domain->sign($post['bizData'], $merchPri);
		
		
		var_dump($merchPri);
		echo '<br><br><br>';
		var_dump($post);
		die;
		
		// 保存位日志
		$this->saveLog(" 请求报文明文:".json_encode($post, 320));
		
		$apiUrl = $domain->getApiUrl();
		$result = $domain->http_post_json($apiUrl, $post);
		
		// 保存位日志
		$this->saveLog(" 返回加密报文:".$result);
		
		$data = json_decode($result, true);
		echo "code:".$data['respCode'].",".$data['respDesc']."\n";
		if($data['respCode'] == 'success'){
			// 平台公钥验证签名
			$sign = $data['sign'];
			unset($data['sign']);
			$plainText = $data['bizData'];
			$res       = $domain->verify($plainText, $sign, $pubKey);
			if($res){
				echo "签名验证通过\n";
				$resss = $domain->Decrypt($data, $merchPri);
				print_r($resss);
			} else{
				echo "签名验证失败\n";
			}
		}
		
	}
	
	
	// 获取订单号
	protected function getOrderid($uid)
	{
		$orderid = $uid.'_'.date('YmdHis').rand(100, 999);
		
		return $orderid;
	}
	#####################################################################################################################################
	
	/**
	 * 微信支付获取订单号
	 * @desc 用于 微信支付获取订单号
	 * @return int code 操作码，0表示成功
	 * @return array info
	 * @return string info[0] 支付信息
	 * @return string msg 提示信息
	 */
	public function getWxOrder()
	{
		$uid      = checkNull($this->uid);
		$token    = checkNull($this->token);
		$changeid = checkNull($this->changeid);
		$coin     = checkNull($this->coin);
		$money    = checkNull($this->money);
		
		$checkToken = checkToken($uid, $token);
		if($checkToken == 700){
			return $this->fail('您的登陆状态失效，请重新登陆！', $checkToken);
		}
		
		$orderid = $this->getOrderid($uid);
		$type    = 2;
		if($coin == 0){
			return $this->fail('信息错误', 1002);
		}
		
		$configpri = getConfigPri();
		$configpub = getConfigPub();
		//配置参数检测
		if($configpri['wx_appid'] == "" || $configpri['wx_mchid'] == "" || $configpri['wx_key'] == ""){
			return $this->fail('微信未配置', 1002);
		}
		
		$orderinfo = array("uid" => $uid, "touid" => $uid, "money" => $money, "coin" => $coin, "orderno" => $orderid, "type" => $type, "status" => 0, "addtime" => time());
		$domain    = new Domain_Charge();
		$info      = $domain->getOrderId($changeid, $orderinfo);
		if($info == 1003){
			return $this->fail('订单信息有误，请重新提交', 1003);
		} elseif(!$info){
			return $this->fail('订单生成失败', 1001);
		}
		
		$noceStr  = md5(rand(100, 1000).time());//获取随机字符串
		$time     = time();
		$paramarr = array(
			"appid"        => $configpri['wx_appid'],
			"body"         => "充值{$coin}虚拟币",
			"mch_id"       => $configpri['wx_mchid'],
			"nonce_str"    => $noceStr,
			"notify_url"   => $configpub['site'].'/appapi/pay/notify_wx',
			"out_trade_no" => $orderid,
			"total_fee"    => $money * 100,
			"trade_type"   => "APP",
		);
		
		$sign             = $this->sign($paramarr, $configpri['wx_key']);//生成签名
		$paramarr['sign'] = $sign;
		$paramXml         = "<xml>";
		foreach($paramarr as $k => $v){
			$paramXml .= "<".$k.">".$v."</".$k.">";
		}
		$paramXml .= "</xml>";
		
		$ch = curl_init();
		@curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 跳过证书检查
		@curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, true);  // 从证书中检查SSL加密算法是否存在
		@curl_setopt($ch, CURLOPT_URL, "https://api.mch.weixin.qq.com/pay/unifiedorder");
		@curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		@curl_setopt($ch, CURLOPT_POST, 1);
		@curl_setopt($ch, CURLOPT_POSTFIELDS, $paramXml);
		@$resultXmlStr = curl_exec($ch);
		if(curl_errno($ch)){
			//print curl_error($ch);
			file_put_contents(API_ROOT.'/../log/phalapi/charge_wxpay_'.date('Y-m-d').'.txt', date('y-m-d H:i:s').' 提交参数信息 ch:'.json_encode(curl_error($ch))."\r\n\r\n", FILE_APPEND);
		}
		
		curl_close($ch);
		$result2 = $this->xmlToArray($resultXmlStr);
		if($result2['return_code'] == 'FAIL'){
			return $this->fail($result2['return_msg'], 1005);
		}
		
		$time2             = time();
		$prepayid          = $result2['prepay_id'];
		$sign              = "";
		$noceStr           = md5(rand(100, 1000).time());//获取随机字符串
		$paramarr2         = array("appid" => $configpri['wx_appid'], "noncestr" => $noceStr, "package" => "Sign=WXPay", "partnerid" => $configpri['wx_mchid'], "prepayid" => $prepayid, "timestamp" => $time2);
		$paramarr2["sign"] = $this->sign($paramarr2, $configpri['wx_key']);//生成签名
		
		return $this->success(['0' => $paramarr2]);
	}
	
	
	/**
	 * 支付宝支付获取订单号
	 * @desc 用于支付宝支付获取订单号
	 * @return int code 操作码，0表示成功
	 * @return array info
	 * @return string info[0].orderid 订单号
	 * @return string msg 提示信息
	 */
	public function getAliOrder()
	{
		$rs       = array('code' => 0, 'msg' => '', 'info' => array());
		$uid      = checkNull($this->uid);
		$token    = checkNull($this->token);
		$changeid = checkNull($this->changeid);
		$coin     = checkNull($this->coin);
		$money    = checkNull($this->money);
		
		$checkToken = checkToken($uid, $token);
		if($checkToken == 700){
			return $this->fail('您的登陆状态失效，请重新登陆！', $checkToken);
		}
		
		$configpri = getConfigPri();
		if(!$configpri['aliapp_partner'] || !$configpri['aliapp_seller_id'] || !$configpri['aliapp_key_android'] || !$configpri['aliapp_key_ios']){
			return $this->fail('支付宝未配置！', 1001);
		}
		
		$orderid = $this->getOrderid($uid);
		$type    = 1;
		if($coin == 0){
			return $this->fail('信息错误', 1002);
		}
		
		$orderinfo = array("uid" => $uid, "touid" => $uid, "money" => $money, "coin" => $coin, "orderno" => $orderid, "type" => $type, "status" => 0, "addtime" => time());
		$domain    = new Domain_Charge();
		$info      = $domain->getOrderId($changeid, $orderinfo);
		if($info == 1003){
			$code = 1003;
			$msg  = '订单信息有误，请重新提交';
		} elseif(!$info){
			$code = 1001;
			$msg  = '订单生成失败';
		}
		
		return $this->fail($msg, $code, ['0' => ['orderid' => $orderid]]);
	}
	
	
	/**
	 * sign拼装获取
	 */
	protected function sign($param, $key)
	{
		$sign = "";
		ksort($param);
		foreach($param as $k => $v){
			$sign .= $k."=".$v."&";
		}
		
		$sign .= "key=".$key;
		$sign = strtoupper(md5($sign));
		
		return $sign;
	}
	
	/**
	 * xml转为数组
	 */
	protected function xmlToArray($xmlStr)
	{
		$msg     = array();
		$postStr = $xmlStr;
		$msg     = (array)simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
		
		return $msg;
	}
	
	
}
